﻿using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;

namespace Framework.Core.Domain
{
    public abstract class EntityBase<IdT>
    {
        private IdT id = default(IdT);

        /// <summary>
        /// 针对不同类型的ID
        /// </summary>
        public virtual IdT ID
        {
            get { return id; }
            set { id = value; }
        }

        /// <summary>
        /// Transient objects are not associated with an item already in storage.  For instance,
        /// </summary>
        //public virtual bool IsTransient()
        //{
        //    return ID == null || ID.Equals(default(IdT));
        //}

        public virtual bool ValueEquals(object obj)
        {
            EntityBase<IdT> o = obj as EntityBase<IdT>;
            if (o == null)
            {
                return false;
            }

            Type objT = obj.GetType();
            Type thisT = this.GetType();
            //类型不相等
            if (!objT.Equals(thisT))
            {
                return false;
            }

            //if (o.ID.Equals(this.ID))
            //{
            foreach (PropertyInfo p in objT.GetProperties())
            {
                object objV = p.GetValue(o, null);
                object thisV = p.GetValue(this, null);
                if (!this.ObjectValueEquals(objV, thisV))
                {
                    return false;
                }
            }
            return true;
            //}
            //return false;
        }

        private bool ObjectValueEquals(object obj1, object obj2)
        {
            //同时为null返回true
            if (obj1 == null && obj2 == null)
            {
                return true;
            }
            //其中一个为null都返回false
            if (obj1 == null || obj2 == null)
            {
                return false;
            }
            //类型不同返回false
            if (obj1.GetType().FullName != obj2.GetType().FullName)
            {
                return false;
            }

            if (obj1 is EntityBase<IdT>)
            {
                return ((EntityBase<IdT>)obj1).ValueEquals(obj2);
            }
            else if (obj1 is IEnumerable)
            {
                foreach (object obj1Item in (IEnumerable)obj1)
                {
                    foreach (object obj2Item in (IEnumerable)obj2)
                    {
                        if (!ObjectValueEquals(obj1Item, obj2Item))
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
            else
            {
                return obj1.Equals(obj2);
            }
        }
    }
}
